package ru.ifmo;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import ru.ifmo.entities.UsersEntity;
import ru.ifmo.mail.MailSender;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.mail.MessagingException;
import javax.naming.NamingException;
import java.util.Iterator;

public class RegisterBean {
    @NotEmpty(message = "??????? ?????")
    @Length(min = 3, max = 10, message = "????? ?????? ?? 3 ?? 10 ????????")
    private String login;
    @NotEmpty(message = "??????? ??????")
    @Length(min = 5, max = 15, message = "????? ?????? ?? 5 ?? 10 ????????")
    private String password;
    @NotEmpty(message = "??????? ?????? ????????")
    private String confirmPassword;
    @NotEmpty(message = "??????? ???? ???")
    private String firstName;
    @NotEmpty(message = "??????? ???????")
    private String lastName;
    @Email(message = "??????? ?????????? e-mail")
    @NotEmpty(message = "???????")
    private String email;

    private boolean registered;

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getConfirmPassword() {
        return confirmPassword;
    }

    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public boolean isRegistered() {
        return registered;
    }

    public void doRegisterListener(ActionEvent event) {
        final FacesContext context = FacesContext.getCurrentInstance();
        final UIComponent parentComponent = event.getComponent().getParent();
        if (confirmPassword == null || password == null) {

        } else if (confirmPassword.equals(password)) {
            try {
                if (checkUserExists()) {
                    addMessage(context, "???? ????? ??? ?????", parentComponent.findComponent("regLogin"));
                }
            } catch (RuntimeException e) {
                addMessage(context, "???????? ???????? ? ??", parentComponent.findComponent("regLogin"));
            }
        } else {
            addMessage(context, "?????? ?? ???????", parentComponent.findComponent("regPass"));
            addMessage(context, "?????? ?? ???????", parentComponent.findComponent("regConfirmPass"));
        }
    }

    private void addMessage(final FacesContext context, final String message, final UIComponent component) {
        if (component != null) {
            final String clientId = component.getClientId(context);
            context.addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
        }
    }

    public String clear() {
        clearData();
        clearMessages();
        return "cleared";
    }

    private void clearData() {
        login = null;
        password = null;
        confirmPassword = null;
        firstName = null;
        lastName = null;
        email = null;
        registered = false;
    }

    private void clearMessages() {
        FacesContext context = FacesContext.getCurrentInstance();
        final Iterator<String> clients = context.getClientIdsWithMessages();
        while (clients.hasNext()) {
            final String clientId = clients.next();
            final Iterator<FacesMessage> messages = context.getMessages(clientId);
            while (messages.hasNext()) {
                messages.next();
                messages.remove();
            }
        }
    }

    public String doRegister() {
        if (FacesContext.getCurrentInstance().getMaximumSeverity() != null) {
            return "fail";
        }
        final Session registerSession = HibernateUtil.getSession();
        try {
            if (checkUserExists(registerSession)) {
                return "fail";
            }
            createUser(registerSession);
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        } finally {
            registerSession.close();
        }
        registered = true;
        doAutoLogin();
        try {
            MailSender.sendMessage("andy2005@yandex.ru", "??????????? ? ??????? ?????? ???????????? iShop!",
                    "<h3>????????? " + firstName + " " + lastName + "!</h3>" +
                            "<p>??????????? ? ???????? ???????????? ?? ????? ?????? ???????????? ???????????.<br/> " +
                            "?????? ?? ?????? ?????? ?????????? ? ????????? ?????????????.<br>" +
                            "? ??? ? ??? ????? ??????????? ??????, ? ??? ??? ?? ?????? ?? ????!</p>" +
                            "<br/>---<br/>" +
                            "<p>? ?????????,<br/>" +
                            "????????????? ????? iShop");
        } catch (MessagingException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (NamingException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return "success";
    }

    private void doAutoLogin() {
        final FacesContext context = FacesContext.getCurrentInstance();
        final ExternalContext externalContext = context.getExternalContext();
        final LoginBean loginBean = (LoginBean) externalContext.getSessionMap().get("loginBean");
        if (loginBean != null) {
            loginBean.setLogin(login);
            loginBean.setPassword(password);
            loginBean.doLogin();
        }
    }

    private void createUser(final Session registerSession) {
        final Transaction transaction = registerSession.beginTransaction();
        try {
            final UsersEntity entity = new UsersEntity();
            entity.setLogin(login);
            entity.setPassword(password);
            entity.setEmail(email);
            entity.setFirstName(firstName);
            entity.setLastName(lastName);
            registerSession.save(entity);
            transaction.commit();
        } catch (RuntimeException e) {
            transaction.rollback();
            throw e;
        }
    }

    private boolean checkUserExists() {
        final Session session = HibernateUtil.getSession();
        try {
            return checkUserExists(session);
        } finally {
            session.close();
        }
    }

    private boolean checkUserExists(final Session session) {
        final Query query = session.createQuery("from UsersEntity u where u.login = :login");
        query.setString("login", login);
        final boolean userExists = query.iterate().hasNext();
        return userExists;
    }
}
